#include "GCore.h"
#include "GCameraController.h"
#include <filesystem>
#include <string>
#include <DirectXMath.h>

#include <Vendor\IMGUI\imgui_impl_win32.h>
#include <GGenericInfra\GGiEngineUtil.h>
#include <IMGUI\ImGuizmo.h>
#include <GRendererInfra\GRiMeshLoader.h>
#include <GGenericInfra\Mouse.h>
#include <GGenericInfra\Keyboard.h>
#include <GRendererInfra\GRiObj.h>
#include "..\GRTX\GRTXRenderer.h"
#include<Windows.h>    
#include <tchar.h> 
#include <thread>
#include "..\GRTX\GRTXScene.h"
#include "..\GRTX\GRTXBVH.h"
#include <GGiThreadPool.h>

using namespace DirectX;
using namespace std;
using namespace std::filesystem;
GCore::~GCore()
{
	mImgui->ShutDown();
	
}

GCore& GCore::GetCore()
{
	static GCore* instance = new GCore();

	return *instance;
}

void GCore::Run()
{
	MSG msg = { 0 };

	mTimer->Reset();

	while (msg.message != WM_QUIT)
	{
		// If there are Window messages then process them.
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		// Otherwise, do animation/game stuff.
		else
		{
			mTimer->Tick();

			if (!mAppPaused)
			{
				
				Update();
				Draw();
			}
			else
			{
				Sleep(100);
			}
		}
	}
}

#pragma region Export


void GCore::SaveScene()
{
	mScene->SaveProject(ProjectName, mSkyCubeFileName, mSceneObjectLayer[(int)RenderLayer::Default], mMeshes);
}

int GCore::GetSceneObjectNum()
{
	return (int)(mSceneObjectLayer[(int)RenderLayer::Default].size());
}

const char* GCore::GetSceneObjectName(int index)
{
	return mSceneObjectLayer[(int)RenderLayer::Default][index]->UniqueName.c_str();
}
#pragma endregion Export

void GCore::RenderFrame()
{
	Update();

	Draw();
}

void GCore::Initialize(HWND OutputWindow, double width, double height)
{

	//初始化鼠标键盘
	Mouse::Get().SetWindow(OutputWindow);
	Mouse::Get().SetMode(Mouse::MODE_ABSOLUTE);
	Keyboard::Get();

	mRenderer->PreInitialize(OutputWindow, width, height);

	LoadScene();

	mFactory = mRenderer->GetFactory();

	CreateImgui();

	if (!LoadAllTexture())
		return;
	mRenderer->SyncTextures(mTextures);

// 	LoadMaterials();
// 	mRenderer->SyncMaterials(mMaterials);

	LoadMeshes();
	mRenderer->SyncMeshes(mMeshes);

	LoadSceneObjects();
	mRenderer->SyncSceneObjects(mSceneObjects,mSceneObjectLayer);

	LoadCamera();
	mRenderer->SetCamera(m_pCamera.get());

	mRenderer->SetExternData(mINI);
	mRenderer->Initialize();
}

// Forward declare message handler from imgui_impl_win32.cpp
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

void GCore::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
#ifdef USE_IMGUI
	ImGui_ImplWin32_WndProcHandler(hwnd, msg, wParam, lParam);
#endif 
	switch (msg)
	{
		// WM_ACTIVATE is sent when the window is activated or deactivated.
		// We pause the game when the window is deactivated and unpause it
		// when it becomes active.
	case WM_ACTIVATE:
		if (LOWORD(wParam) == WA_INACTIVE)
		{
			mAppPaused = true;
			mTimer->Stop();
		}
		else
		{
			mAppPaused = false;
			mTimer->Start();
		}
		return ;

		// WM_SIZE is sent when the user resizes the window.
	case WM_SIZE:
		// Save the new client area dimensions.
		mRenderer->SetClientWidth(LOWORD(lParam));
		mRenderer->SetClientHeight(HIWORD(lParam));
		if (mRenderer->IsRunning())
		{
			if (wParam == SIZE_MINIMIZED)
			{
				mAppPaused = true;
				mMinimized = true;
				mMaximized = false;
			}
			else if (wParam == SIZE_MAXIMIZED)
			{
				mAppPaused = false;
				mMinimized = false;
				mMaximized = true;
				OnResize();
			}
			else if (wParam == SIZE_RESTORED)
			{

				// Restoring from minimized state?
				if (mMinimized)
				{
					mAppPaused = false;
					mMinimized = false;
					OnResize();
				}

				// Restoring from maximized state?
				else if (mMaximized)
				{
					mAppPaused = false;
					mMaximized = false;
					OnResize();
				}
				else if (mResizing)
				{
					// If user is dragging the resize bars, we do not resize
					// the buffers here because as the user continuously
					// drags the resize bars, a stream of WM_SIZE messages are
					// sent to the window, and it would be pointless (and slow)
					// to resize for each WM_SIZE message received from dragging
					// the resize bars.  So instead, we reset after the user is
					// done resizing the window and releases the resize bars, which
					// sends a WM_EXITSIZEMOVE message.
				}
				else // API call such as SetWindowPos or mSwapChain->SetFullscreenState.
				{
					OnResize();
				}
			}
		}
		return; 0;

		// WM_EXITSIZEMOVE is sent when the user grabs the resize bars.
	case WM_ENTERSIZEMOVE:
		mAppPaused = true;
		mResizing = true;
		mTimer->Stop();
		return; 0;

		// WM_EXITSIZEMOVE is sent when the user releases the resize bars.
		// Here we reset everything based on the new window dimensions.
	case WM_EXITSIZEMOVE:
		mAppPaused = false;
		mResizing = false;
		mTimer->Start();
		OnResize();
		return; 0;

		// WM_DESTROY is sent when the window is being destroyed.
	case WM_DESTROY:
		PostQuitMessage(0);
		return; 0;

		// The WM_MENUCHAR message is sent when a menu is active and the user presses
		// a key that does not correspond to any mnemonic or accelerator key.
	case WM_MENUCHAR:
		// Don't beep when we alt-enter.
		return; MAKELRESULT(0, MNC_CLOSE);

		// Catch this message so to prevent the window from becoming too small.
	case WM_GETMINMAXINFO:
		((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
		((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
		return; 0;

	case WM_ACTIVATEAPP:
		Mouse::ProcessMessage(msg, wParam, lParam);
		Keyboard::ProcessMessage(msg, wParam, lParam);
		break;
    case WM_INPUT:
    case WM_MOUSEMOVE:
    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_RBUTTONDOWN:
    case WM_RBUTTONUP:
    case WM_MBUTTONDOWN:
    case WM_MBUTTONUP:
    case WM_MOUSEWHEEL:
    case WM_XBUTTONDOWN:
    case WM_XBUTTONUP:
    case WM_MOUSEHOVER:
        Mouse::ProcessMessage(msg, wParam, lParam);
		break;

	case WM_KEYUP:
		if (wParam == VK_ESCAPE)
		{
			PostQuitMessage(0);
		}
    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
    case WM_SYSKEYUP:
        Keyboard::ProcessMessage(msg, wParam, lParam);
        break;
		

		return; 0;
	}
}

std::vector<std::string> GCore::FindFileInFolder(const std::string& relPath, const std::vector<std::string>& formats, bool bCheckFormat)
{
	vector<string> files;

	string fullPath = WorkDir + relPath;

	path str(fullPath);
	if (!exists(str))		//必须先检测目录是否存在才能使用文件入口.
		return files;
	directory_entry entry(str);		//文件入口
	assert (entry.status().type() == file_type::directory);

	directory_iterator list(str);	        //文件入口容器
	
	for (auto& it : list)
	{
		if (it.is_directory())
		{
			vector<string> temp = move(FindFileInFolder(relPath + "\\" + it.path().filename().string(), formats, bCheckFormat));
			files.insert(files.end(), temp.begin(), temp.end());
		}
		else
		{
			for (auto& fm:formats)
			{
				if (it.path().extension().string() == fm)
				{
					files.emplace_back(it.path().relative_path().string());
					break;
				}
			}
		}
		
	}

	return files;
}

void GCore::OnResize()
{
	mRenderer->OnResize();
}

void GCore::Update()
{
	float dt = mTimer->DeltaTime();

	GCameraController::UpdataCamera(m_pCamera.get(), m_CameraMode, dt,mCameraSpeed);

	if (mINI & INI_UseIMGUI)
	{
		UpdateGui();

		ImGui::Begin("RTXSetting");

		static int spp = 1;
		static float prr = 0.75;
		static int maxPrimitive = 10;
		static size_t process = 0;
		static std::vector<GMath::Vector3> framebuffer;
		static bool Begin = false;
		static GGiThreadPool pool(1);
		

		ImGui::DragInt("SampleTimes", &spp, 1.0f, 1, 50);
		ImGui::DragFloat("PRR", &prr, 0.005f, 0.1, 0.95);
		ImGui::DragInt("BVHAcceler", &maxPrimitive,(1.0f),1);

			if (ImGui::Button("StartRTX") && !Begin)
			{
				pool.start();
				Begin = true;
				GRTXScene::Get().InitRTX(mSceneObjectLayer[(int)RenderLayer::Default],
					m_pCamera,
					mRenderer->GetClientWidth(),
					mRenderer->GetClientHeight(),
					prr,
					maxPrimitive
				);
				auto f = []() {GRTXRenderer::Get().Render(framebuffer, process, GRTXScene::Get(), spp); };
				pool.appendTask(f);
			}

		if(Begin)
		{
			auto all = mRenderer->GetClientWidth() *
				mRenderer->GetClientHeight() * 1.0f;

			ImGui::ProgressBar(process * 1.0f / all);			
		}

		if (ImGui::Button("ImageGen"))
		{
			pool.stop();

			Begin = false;
			FILE* fp;
			fopen_s(&fp, "binary.ppm", "wb");
			(void)fprintf(fp, "P6\n%d %d\n255\n", mRenderer->GetClientWidth(), mRenderer->GetClientHeight());
			for (auto i = 0; i < mRenderer->GetClientHeight() * mRenderer->GetClientWidth(); ++i) {
				static unsigned char color[3];
				color[0] = (unsigned char)(255 * std::pow(GGiEngineUtil::Clamp(0, 1, framebuffer[i][0]), 0.6f));
				color[1] = (unsigned char)(255 * std::pow(GGiEngineUtil::Clamp(0, 1, framebuffer[i][1]), 0.6f));
				color[2] = (unsigned char)(255 * std::pow(GGiEngineUtil::Clamp(0, 1, framebuffer[i][2]), 0.6f));
				fwrite(color, 1, 3, fp);
			}
			fclose(fp);

			process = 0;
		}
		ImGui::End();
	}
	mRenderer->Update(dt);
	
	Mouse::ButtonStateTracker::Get().Update(Mouse::Get().GetState());
}




void GCore::UpdateGui()
{

	mImgui->BeginFrame();


	ImGui::Begin("ka");
	if (mSelectedSceneObject != nullptr && mSelectedSceneObject->HasComponent<GRiCmpMaterial>())
	{
		ImGui::InputFloat3("kd", mSelectedSceneObject->GetComponent<GRiCmpMaterial>()->Mat.kd.mData);
		if (mSelectedSceneObject->HasComponent<GRiCmpLight>())
		{
			auto point = mSelectedSceneObject->GetComponent<GRiCmpLight>()->pLight.get();
			auto p = reinterpret_cast<GRiPointLight*>(point);
			ImGui::InputFloat3("Color", mSelectedSceneObject->GetComponent<GRiCmpLight>()->pLight->Color.mData);
			ImGui::InputFloat("Intensity", &mSelectedSceneObject->GetComponent<GRiCmpLight>()->pLight->Intensity);
			ImGui::InputFloat("Range", &p->Range);
		}
	}
	
	ImGui::End();
	bool bSelectionNotNull = (mSelectedSceneObject != nullptr);
	ImGuizmo::Enable(bSelectionNotNull);
	float view[16];
	float proj[16];
	float objLoc[3];
	float objRot[3];
	float objScale[3];
	GMath::Vector3 prevLoc;
	GMath::Vector3 prevRot;
	GMath::Vector3 prevScale;
	if (bSelectionNotNull)
	{
		for (auto i = 0u; i < 4; i++)
		{
			for (auto j = 0u; j < 4; j++)
			{
				view[i * 4 + j] = m_pCamera->GetView().m[i][j];
				proj[i * 4 + j] = m_pCamera->GetProj().m[i][j];
				prevLoc = mSelectedSceneObject->GetComponent<GRiCmpTransform>()->GetLocation();
				objLoc[0] = prevLoc[0];
				objLoc[1] = prevLoc[1];
				objLoc[2] = prevLoc[2];
				prevRot = mSelectedSceneObject->GetComponent<GRiCmpTransform>()->GetRotation();
				objRot[0] = prevRot[0];
				objRot[1] = prevRot[1];
				objRot[2] = prevRot[2];
				prevScale = mSelectedSceneObject->GetComponent<GRiCmpTransform>()->GetScale();
				objScale[0] = prevScale[0];
				objScale[1] = prevScale[1];
				objScale[2] = prevScale[2];
			}
		}
	}

	mImgui->SetGUIContent(
		bSelectionNotNull,
		view,
		proj,
		objLoc,
		objRot,
		objScale,
		mCameraSpeed,
		mRenderer->GetClientWidth(),
		mRenderer->GetClientHeight()
	);

	bool bDirty = bSelectionNotNull && (objLoc[0] != prevLoc[0] || objLoc[1] != prevLoc[1] || objLoc[2] != prevLoc[2] ||
		objRot[0] != prevRot[0] || objRot[1] != prevRot[1] || objRot[2] != prevRot[2] ||
		objScale[0] != prevScale[0] || objScale[1] != prevScale[1] || objScale[2] != prevScale[2]
		);
	if (bDirty)
	{
		mSelectedSceneObject->GetComponent<GRiCmpTransform>()->SetLocation(objLoc[0], objLoc[1], objLoc[2]);
		mSelectedSceneObject->GetComponent<GRiCmpTransform>()->SetRotation(objRot[0], objRot[1], objRot[2]);
		mSelectedSceneObject->GetComponent<GRiCmpTransform>()->SetScale(objScale[0], objScale[1], objScale[2]);
		/*mGuiCallback->RefreshSceneObjectTransformCallback();*/
	}
}

void GCore::Draw()
{
	float dt = mTimer->DeltaTime();

	mRenderer->Draw(dt);
}

void GCore::SelectSceneObject(char* sceneObjectName)
{
	std::string SceneObjectNameStr(sceneObjectName);
	if (mSceneObjects.find(SceneObjectNameStr) == mSceneObjects.end())
	{
		return;
	}
	mSelectedSceneObject = mSceneObjects[SceneObjectNameStr].get();
}
void GCore::CreateSceneObject(char* sceneObjectName, char* meshUniqueName)
{
	std::string SceneObjectNameStr(sceneObjectName);
	std::string MeshUniqueNameStr(meshUniqueName);
	if (mSceneObjects.find(SceneObjectNameStr) != mSceneObjects.end())
	{
		return;
	}
	if (mMeshes.find(MeshUniqueNameStr) == mMeshes.end())
	{
		return;
	}
	GUPtr<GRiObj> newSceneObject(new GRiObj());
	newSceneObject->UniqueName = SceneObjectNameStr;
	newSceneObject->GetComponent<GRiCmpTransform>()->SetScale(1, 1, 1);

	GUPtr<GRiCmpGeometry> cmpG(new GRiCmpGeometry());
	cmpG->SetMesh(mMeshes[MeshUniqueNameStr].get());
	newSceneObject->AddComponent(move(cmpG));

	GUPtr<GRiCmpMaterial> cmpM(new GRiCmpMaterial());
	newSceneObject->AddComponent(move(cmpM));

	mSceneObjectLayer[(int)RenderLayer::Default].push_back(newSceneObject.get());
	mSceneObjects[newSceneObject->UniqueName] = std::move(newSceneObject);
	mRenderer->SyncSceneObjects(mSceneObjects, mSceneObjectLayer);
}

bool GCore::SceneObjectExists(char* tryName) const
{
	std::string name(tryName);

	return mSceneObjects.find(name) != mSceneObjects.end();
}

void GCore::DeleteSceneObject(char* deleteName) 
{
	std::string name(deleteName);
	if (mSceneObjects.find(name) == mSceneObjects.end())
	{
		return;
	}
	auto it = std::find(mSceneObjectLayer[(int)RenderLayer::Default].begin(),
		mSceneObjectLayer[(int)RenderLayer::Default].end(),
		mSceneObjects[name].get());

	if (it != mSceneObjectLayer[(int)RenderLayer::Default].end())
	{
		mSceneObjectLayer[(int)RenderLayer::Default].erase(it);
	}
	mSceneObjects.erase(name);
	//mRenderer->SyncSceneObjects(mSceneObjects, mSceneObjectLayer);
}

void GCore::SetProjectName(char* projName)
{
	ProjectName = projName;
}

void GCore::GetSceneObjectTransform(char* objName, float* trans)
{
	std::string sObjectName(objName);
	if (mSceneObjects.find(sObjectName) == mSceneObjects.end())
	{
		return;
	}

	GMath::Vector3 loc = mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->GetLocation();
	GMath::Vector3 rot = mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->GetRotation();
	GMath::Vector3 scale = mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->GetScale();

	trans[0] = loc[0];
	trans[1] = loc[1];
	trans[2] = loc[2];
	trans[3] = rot[0];
	trans[4] = rot[1];
	trans[5] = rot[2];
	trans[6] = scale[0];
	trans[7] = scale[1];
	trans[8] = scale[2];
}

void GCore::SetSceneObjectTransform(char* objName, float* trans)
{
	std::string sObjectName(objName);
	if (mSceneObjects.find(sObjectName) == mSceneObjects.end())
	{
		return;
	}

	mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->SetLocation(trans[0], trans[1], trans[2]);
	mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->SetRotation(trans[3], trans[4], trans[5]);
	mSceneObjects[sObjectName]->GetComponent<GRiCmpTransform>()->SetScale(trans[6], trans[7], trans[8]);
}

const char* GCore::GetSceneObjectMeshName(char* objName)
{
	std::string sObjectName(objName);
	if (mSceneObjects.find(sObjectName) == mSceneObjects.end())
	{
		return nullptr;
	}

	auto str = mSceneObjects[sObjectName]->GetComponent<GRiCmpGeometry>()->GetName();
	return str;
}

void GCore::SetSceneObjectMesh(char* sceneObjectName, char* meshUniqueName)
{
	std::string sObjectName(sceneObjectName);
		std::string meshName(meshUniqueName);
	if (mSceneObjects.find(sObjectName) == mSceneObjects.end())
	{
		return ;
	}
	if (mMeshes.find(meshName) == mMeshes.end())
	{
		return ;
	}
	//assert(mSceneObjects[sObjectName].get() == mSelectedSceneObject);

	return mSelectedSceneObject->GetComponent<GRiCmpGeometry>()->SetMesh(mMeshes[meshName].get());
}

bool GCore::LoadAllTexture()
{
	unique_ptr<GRiTextureLoader> texloader(mFactory->CreateTextureLoader());

	
	WorkDir = "Project\\Content\\";

	vector<string> formats{".dds",".png",".jpg"};

	decltype(formats) files = move(FindFileInFolder("Textures", formats, true));
	
	
	GRiTexture* tex;
	for (auto& fileName : files)
	{
		tex = texloader->LoadTexture(fileName);
		tex->UniqueFileName = fileName;

		unique_ptr<GRiTexture> temp(tex);
		mTextures.insert(std::pair<string, unique_ptr<GRiTexture>>(tex->UniqueFileName, move(temp)));
	}


	// SkyCubeMap
	mSkyCubeFileName = mScene->mSkyCubemapUniqueName;
	
	tex = texloader->LoadTexture(mSkyCubeFileName,true);	
	tex->UniqueFileName = "SkyCube";
	unique_ptr<GRiTexture> temp(tex);

	mTextures.insert(std::pair<string, unique_ptr<GRiTexture>>(tex->UniqueFileName, move(temp)));

	return true;
}


void GCore::LoadMaterials()
{
	


}

void GCore::LoadMeshes()
{
	unique_ptr<GRiGeometryGenerator> geo(mFactory->CreateGeometryGenerator());
	#pragma region SysShape
	{
		{
			auto data = geo->CreateBox(1, 1, 1, 0);
			auto mesh = mFactory->CreateMesh(data);
			mesh->UniqueName = "Box";
			mesh->Name = "Box";
			mMeshes[mesh->UniqueName].reset(mesh);			
		}		
		{
			auto data = geo->CreateSphere(1,20,20);
			auto mesh = mFactory->CreateMesh(data);
			mesh->UniqueName = "Sphere";
			mesh->Name = "Sphere";
			mMeshes[mesh->UniqueName].reset(mesh);
		}
		{
			auto data = geo->CreateGrid(10,10,10,10);
			auto mesh = mFactory->CreateMesh(data);
			mesh->UniqueName = "Plane";
			mesh->Name = "Plane";
			mMeshes[mesh->UniqueName].reset(mesh);
		}
	}
#pragma endregion SysShape

	{
		GRiMeshData cMeshData = geo->CreateQuad(-1,-1,2,2);
		auto mesh = mFactory->CreateMesh(cMeshData);
		mesh->UniqueName = "FullQuad";
		mesh->Name = "Quad";
		mMeshes[mesh->UniqueName].reset(mesh);
	}

	vector<string> formats{ ".obj"};

	decltype(formats) files = move(FindFileInFolder("Models", formats, true));
	GRiMeshData* mesh;
	for (auto& fileName : files)
	{
		vector<GRiMeshData> cMeshData;
		GRiMeshLoader::Get().ImportMesh(fileName, cMeshData);
		GRiMeshData me;
		for (auto m:cMeshData)
		{
			me.Vertices.insert(me.Vertices.end(),m.Vertices.begin(),m.Vertices.end());
			me.Indices.insert(me.Indices.end(), m.Indices.begin(), m.Indices.end());
			
		}
		
		
		auto mesh = mFactory->CreateMesh(me);
		mesh->UniqueName = fileName;

		mMeshes[mesh->UniqueName].reset(mesh);
	}

}

void GCore::LoadSceneObjects()
{
	
	GUPtr<GRiObj> skySo(new GRiObj());
	skySo->UniqueName = "Sky";
	GUSPtr<GRiCmpGeometry> cmpGeo(new GRiCmpGeometry());
	skySo->AddComponent(cmpGeo);
	cmpGeo->SetMesh(mMeshes["FullQuad"].get());
	mSceneObjectLayer[(int)RenderLayer::Sky].push_back(skySo.get());
	mSceneObjects[skySo->UniqueName] = move(skySo);

	for (int i = 0 ;i < 4;i++)
	{
		GUPtr<GRiObj> debugSo(new GRiObj());
		debugSo->UniqueName = "Debug" + to_string(i);
		GUSPtr<GRiCmpGeometry> cmpGeo(new GRiCmpGeometry());
		debugSo->AddComponent(cmpGeo);
		cmpGeo->SetMesh(mMeshes["FullQuad"].get());
		auto trans = debugSo->GetComponent<GRiCmpTransform>();
		trans->SetScale(0.25f, 0.25, 1);
		trans->SetLocation(-0.75f + i * 0.5f, -0.75, 0);
		mSceneObjectLayer[(int)RenderLayer::DeBug].push_back(debugSo.get());
		mSceneObjects[debugSo->UniqueName] = move(debugSo);
	}
	
	for (int i = 0; i < 1; i++)
	{
		GUPtr<GRiObj> light(new GRiObj());
		light->UniqueName = "Light" + to_string(i);
		GUSPtr<GRiCmpGeometry> cmpGeo(new GRiCmpGeometry());
		light->AddComponent(cmpGeo);
		cmpGeo->SetMesh(mMeshes["FullQuad"].get());
		auto trans = light->GetComponent<GRiCmpTransform>();
		trans->SetRotation(-90, 0, 0);
		trans->SetScale(0.25f, 0.25, 0.25f);
		trans->SetLocation(0 + i * 4,0.99,-1);

		GUPtr<GRiCmpLight> cmpLight(new GRiCmpLight());
		cmpLight->pLight.reset(new GRiPointLight());
		cmpLight->LightId = mSceneObjectLayer[(int)RenderLayer::Light].size();
		cmpLight->pLight->Color = (GMath::Vector3{ 0.747f + 0.058f, 0.747f + 0.258f, 0.747f } *8.0f + GMath::Vector3{ 0.740f + 0.287f, 0.740f + 0.160f, 0.740f }*15.6f + GMath::Vector3{ 0.737f + 0.642f, 0.737f + 0.159f, 0.737f }*18.4f);
		light->AddComponent(std::move(cmpLight));

		GUPtr<GRiCmpMaterial> cmpM(new GRiCmpMaterial());
		cmpM->Mat.kd = GMath::Vector3{ 0.65f,0.65,0.65f };
		light->AddComponent(std::move(cmpM));

		mSceneObjectLayer[(int)RenderLayer::Default].push_back(light.get());
		mSceneObjectLayer[(int)RenderLayer::Light].push_back(light.get());
		
		mSceneObjects[light->UniqueName] = move(light);
	}

	for (auto& info :mScene->mSceneObjectInfo)
	{
		GUPtr<GRiObj> so(new GRiObj());
		so->UniqueName = info.UniqueName;

		auto trans = so->GetComponent<GRiCmpTransform>();
		trans->SetLocation(info.Location[0], info.Location[1], info.Location[2]);
		trans->SetRotation(info.Rotation[0], info.Rotation[1], info.Rotation[2]);
		trans->SetScale(info.Scale[0], info.Scale[1], info.Scale[2]);

		GUPtr<GRiCmpGeometry> cmpGeo(new GRiCmpGeometry());
		// 如果没找到对应的Mesh，就赋予一个box
		if (mMeshes.find(info.MeshUniqueName) != mMeshes.end())
			cmpGeo->SetMesh(mMeshes[info.MeshUniqueName].get());
		else
			cmpGeo->SetMesh(mMeshes["FullQuad"].get());
		so->AddComponent(move(cmpGeo));

	
		// 材质暂时没能序列化
		GUPtr<GRiCmpMaterial> cmpMat(new GRiCmpMaterial());
		cmpMat->Mat.kd = info.Material.KD;
		cmpMat->Mat.ks = { 0.5f,0.5f,0.5f };
		cmpMat->Mat.mBUseBump = true;
		cmpMat->Mat.mTexBump = WorkDir + "Textures\\Resource\\Default_Normal.png";
		so->AddComponent(move(cmpMat));

		mSceneObjectLayer[(int)RenderLayer::Default].push_back(so.get());
		mSceneObjects[so->UniqueName] = move(so);

	}
}

void GCore::LoadCamera()
{
	FirstPersonCamera cam;
	//camera->SetViewPort(0.0f, 0.0f, (float)width, (float)height);

	cam.LookAt(XMVectorSet(0.0f, 0.0f, -5.0f, 0.0f), XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f),
		XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f));

	m_pCamera = std::make_unique<FirstPersonCamera>(cam);


	// 初始化仅在窗口大小变动时修改的值
	m_pCamera->SetFrustum(XM_PI / 3, mRenderer->AspectRatio(), 0.5f, 1000.0f);

}

void GCore::LoadScene()
{
	mScene->Serialize(ProjectName);
}

void GCore::CreateImgui()
{
	mImgui = std::unique_ptr<GRiImgui>(mFactory->CreateImgui());
	mRenderer->SetImgui(mImgui.get());
}

GCore::GCore()
{
	mTimer = std::make_unique<GRiTimer>();

	mRenderer = &GDxRenderer::GetRenderer();

	mScene = std::make_unique<GScene>();
}
